#include "deploy/m_i2c_deploy.h"
#include "m_i2c.h"
#include "inner/i2c_for_pico.h"
#include "m_mutex.h"

#define LOG_TAG "I2C_SERVER"
#include "m_log.h"

typedef struct MI2CObjTag
{
    MMutex lock_;

    Int32 sda_pin_;
    Int32 scl_pin_;
    Int32 i2c_no_;
    Int32 i2c_baudrate_;
} MI2CObj;

static Bool    is_init_ = False;
static MI2CObj m_i2c_;

static void scan_i2c_device(void)
{
    if (MMutexEnter(&m_i2c_.lock_))
    {
        for (int addr = 0; addr < (1 << 7); ++addr) {
            // Perform a 1-byte dummy read from the probe address. If a slave
            // acknowledges this address, the function returns the number of bytes
            // transferred. If the address byte is ignored, the function returns
            // -1.

            // Skip over any reserved addresses.
            int ret;
            UInt8 rxdata;

            ret = i2c_read_blocking(m_i2c_.i2c_no_, addr, &rxdata, 1, False);

            if (ret >= 0)
                LOG_D("device exsits, addr=%02X ret=%d", addr, ret);
        }
        MMutexLeave(&m_i2c_.lock_);
    }
}

Int32 MI2CSendData(const UInt8 addr, const UInt8 *data, Int32 data_len)
{
    Int32 result = kErrCodeElse;

    if (MMutexEnter(&m_i2c_.lock_))
    {
        Int32 write_result = i2c_write_blocking(m_i2c_.i2c_no_, addr, data, data_len, False);

        if (write_result >= 0)
        {
            result = write_result;
        }

        MMutexLeave(&m_i2c_.lock_);
    }
    else
    {
        result = kErrCodeGetLockErr;
    }

    return result;
}

Int32 MI2CReadData(const UInt8 addr, UInt8 *buf, Int32 buf_size)
{
    Int32 result = kErrCodeElse;

    if (MMutexEnter(&m_i2c_.lock_))
    {
        Int32 read_result = i2c_read_blocking(m_i2c_.i2c_no_, addr, buf, buf_size, False);

        if (read_result >= 0)
        {
            result = read_result;
        }
    }
    else
    {
        result = kErrCodeGetLockErr;
    }

    return result;
}

Int32 MI2CInit(MI2CArgs* args)
{
    if (args == NULL)
    {
        return kErrCodeParamsErr;
    }

    if (! is_init_)
    {
        m_i2c_.sda_pin_ = args->SDA_pin;
        m_i2c_.scl_pin_ = args->SCL_pin;
        m_i2c_.i2c_no_  = args->i2c_baudrate;
        m_i2c_.i2c_baudrate_ = args->i2c_baudrate;
        // 初始化Pico的I2C接口
        i2c_init(m_i2c_.i2c_no_, m_i2c_.i2c_baudrate_);

        // 设置GPIO引脚为I2C功能

        gpio_set_function(m_i2c_.sda_pin_, GPIO_FUNC_I2C);
        gpio_set_function(m_i2c_.scl_pin_, GPIO_FUNC_I2C);
        gpio_pull_up(m_i2c_.sda_pin_);
        gpio_pull_up(m_i2c_.scl_pin_);

        MMutexCreate(&m_i2c_.lock_);

        scan_i2c_device();
        is_init_ = True;
    }

    return kErrCodeSucc;
}

Int32 MI2CFini(void)
{
    if (is_init_)
    {
        is_init_ = False;

        MMutexDestory(&m_i2c_.lock_);
    }

    return kErrCodeSucc;
}
